#include "Huevo.h"
#include "ActoresConstantes.h"
#include "UtilidadesConstantes.h"

using namespace TP::Juego::Arena::Actores;
using namespace TP::Juego;

Huevo::Huevo(): Actor("", new Rol (HUEVO, HUEVO)){
    _jugadorMiembro = NULL;
}

Huevo::Huevo(const string& pNombre): Actor(pNombre, new Rol (pNombre, HUEVO)) {
    _jugadorMiembro == NULL;
}

Huevo::~Huevo() {}

IColisionado* Huevo::colisionar (IColisionado* pColisionado){
    
     // Ver si se colisiona contra piso o perímetro o contra otra cosa
    if(pColisionado->getRol()->Descripcion() == DESC_PERIMETRO ||
            pColisionado->getRol()->Descripcion() == DESC_PISO) {
        // Colision cilindro-recta
        if (pColisionado->getRol()->Descripcion() == DESC_PERIMETRO) {
            return (IColisionado*) this->colisionarContraPerimetro ((Perimetro*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_PISO) {
            return (IColisionado*) this->colisionarContraPiso ((Piso*)pColisionado);
        }
    }
    else {
        // Colisión de cilindros
//        if(pColisionado) {
//            
//        }
        if (pColisionado->getRol()->Descripcion() == DESC_CERDITO) {
            return (IColisionado*) this->colisionarContraCerdito ((Cerdito*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_MONTICULOHUEVOS) {
            return (IColisionado*) this->colisionarContraMonticuloHuevo ((MonticuloHuevos*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_FRUTA) {
            return (IColisionado*) this->colisionarContraFruta ((Fruta*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == DESC_CAJA) {
            return (IColisionado*) this->colisionarContraCaja ((Caja*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == HUEVO) {
            return (IColisionado*) this->colisionarContraHuevo ((Huevo*)pColisionado);
        }
        else if (pColisionado->getRol()->Descripcion() == PAJARITO) {
            return (IColisionado*) this->colisionarContraPajarito ((Actor*)pColisionado);
        }   
    }
}

Perimetro* Huevo::colisionarContraPerimetro (Perimetro* pPerimetro) {
    if((this->getTrayectoria()->getPosicion()->X() - this->getRadio() < 0) ||
            (this->getTrayectoria()->getPosicion()->X() + this->getRadio() > pPerimetro->getAncho()) ||
            (this->getTrayectoria()->getPosicion()->Y() - this->getRadio() < 0) ||
            (this->getTrayectoria()->getPosicion()->Y() + this->getRadio() > pPerimetro->getAlto()) )
        this->destruir();
    return pPerimetro;
}

Piso* Huevo::colisionarContraPiso (Piso* pPiso) {
    // TODO: hacer choque contra el piso.    
    //this->destruir();
    return pPiso;
}

Cerdito* Huevo::colisionarContraCerdito(Cerdito* pCerdito) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pCerdito->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pCerdito->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pCerdito->decrementarEnergia(this->getPoderAtaqueContraCerditos());
    }
    return pCerdito;
}

Huevo* Huevo::colisionarContraHuevo(Huevo* pHuevo) {
//    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pHuevo->getTrayectoria()->getPosicion()->X(), 2);
//    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pHuevo->getTrayectoria()->getPosicion()->Y(), 2);
//    long int dr = sqrt(dx + dy);
//    long int sumRadio = this->getRadio() + this->getRadio();
//
//    if(dr < sumRadio)
//        this->decrementarEnergia(pHuevo->getPoderAtaqueContraPajarito());
    return pHuevo;
}

MonticuloHuevos* Huevo::colisionarContraMonticuloHuevo(MonticuloHuevos* pMonticuloHuevos) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pMonticuloHuevos->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pMonticuloHuevos->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pMonticuloHuevos->decrementarEnergia(this->getPoderAtaqueContraSuperficie());
    }
    return pMonticuloHuevos;
}

Caja* Huevo::colisionarContraCaja(Caja* pCaja) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pCaja->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pCaja->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        pCaja->decrementarEnergia(this->getPoderAtaqueContraSuperficie());
        if(pCaja->dstruido()) {
            this->getJugadorMiembro()->sumarPuntos(pCaja->getPuntos());
        }
        this->destruir();
    }        
    return pCaja;
}

Fruta* Huevo::colisionarContraFruta(Fruta* pFruta) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pFruta->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pFruta->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        pFruta->destruir();
        this->getJugadorMiembro()->sumarPuntos(pFruta->getPuntos());
    }
    return pFruta;
}

Actor* Huevo::colisionarContraPajarito(Actor* pPajarito) {
    long int dx = pow(this->getTrayectoria()->getPosicion()->X() - pPajarito->getTrayectoria()->getPosicion()->X(), 2);
    long int dy = pow(this->getTrayectoria()->getPosicion()->Y() - pPajarito->getTrayectoria()->getPosicion()->Y(), 2);
    long int dr = sqrt(dx + dy);
    long int sumRadio = this->getRadio() + this->getRadio();
    
    if(dr < sumRadio) {
        this->destruir();
        if(pPajarito->destruido())
        this->getJugadorMiembro()->sumarPuntos(pPajarito->getPuntos());
    }
    return pPajarito;
}

string Huevo::aXML(){

    TiXmlDocument* doc = new TiXmlDocument();
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());

    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

string Huevo::aXML(const string& pPath){

    TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());
    
    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

void Huevo::parseXML (const string& pDescriptor){

    TiXmlDocument doc;
    doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
    this->deElementoXML(doc.FirstChildElement());
}    

Jugador* Huevo::getJugadorMiembro() const {
    return _jugadorMiembro;
}

void Huevo::setJugadorMiembro(Jugador* jugadorMiembro) {
    _jugadorMiembro = jugadorMiembro;
}